@@ -0,0 +1,23 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using System.Windows.Forms; | |||
namespace WInFormApp | |||
{ | |||
static class Program | |||
{ | |||
/// <summary> | |||
/// The main entry point for the application. | |||
/// </summary> | |||
[STAThread] | |||
static void Main() | |||
{ | |||
Application.SetHighDpiMode(HighDpiMode.SystemAware); | |||
Application.EnableVisualStyles(); | |||
Application.SetCompatibleTextRenderingDefault(false); | |||
Application.Run(new StartForm()); | |||
} | |||
} | |||
} |
@@ -0,0 +1,90 @@ | |||
| |||
namespace WInFormApp | |||
{ | |||
partial class StartForm | |||
{ | |||
/// <summary> | |||
/// Required designer variable. | |||
/// </summary> | |||
private System.ComponentModel.IContainer components = null; | |||
/// <summary> | |||
/// Clean up any resources being used. | |||
/// </summary> | |||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> | |||
protected override void Dispose(bool disposing) | |||
{ | |||
if (disposing && (components != null)) | |||
{ | |||
components.Dispose(); | |||
} | |||
base.Dispose(disposing); | |||
} | |||
#region Windows Form Designer generated code | |||
/// <summary> | |||
/// Required method for Designer support - do not modify | |||
/// the contents of this method with the code editor. | |||
/// </summary> | |||
private void InitializeComponent() | |||
{ | |||
this.btnGen = new System.Windows.Forms.Button(); | |||
this.txtIdList = new System.Windows.Forms.TextBox(); | |||
this.button1 = new System.Windows.Forms.Button(); | |||
this.SuspendLayout(); | |||
// | |||
// btnGen | |||
// | |||
this.btnGen.Location = new System.Drawing.Point(12, 385); | |||
this.btnGen.Name = "btnGen"; | |||
this.btnGen.Size = new System.Drawing.Size(170, 64); | |||
this.btnGen.TabIndex = 0; | |||
this.btnGen.Text = "注册"; | |||
this.btnGen.UseVisualStyleBackColor = true; | |||
this.btnGen.Click += new System.EventHandler(this.btnGen_Click); | |||
// | |||
// txtIdList | |||
// | |||
this.txtIdList.Location = new System.Drawing.Point(12, 12); | |||
this.txtIdList.Multiline = true; | |||
this.txtIdList.Name = "txtIdList"; | |||
this.txtIdList.ScrollBars = System.Windows.Forms.ScrollBars.Both; | |||
this.txtIdList.Size = new System.Drawing.Size(443, 346); | |||
this.txtIdList.TabIndex = 1; | |||
// | |||
// button1 | |||
// | |||
this.button1.Location = new System.Drawing.Point(286, 385); | |||
this.button1.Name = "button1"; | |||
this.button1.Size = new System.Drawing.Size(170, 64); | |||
this.button1.TabIndex = 2; | |||
this.button1.Text = "注销"; | |||
this.button1.UseVisualStyleBackColor = true; | |||
this.button1.Click += new System.EventHandler(this.button1_Click); | |||
// | |||
// StartForm | |||
// | |||
this.AutoScaleDimensions = new System.Drawing.SizeF(11F, 24F); | |||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; | |||
this.ClientSize = new System.Drawing.Size(468, 514); | |||
this.Controls.Add(this.button1); | |||
this.Controls.Add(this.txtIdList); | |||
this.Controls.Add(this.btnGen); | |||
this.Name = "StartForm"; | |||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; | |||
this.Text = "TestForm"; | |||
this.Load += new System.EventHandler(this.Form1_Load); | |||
this.ResumeLayout(false); | |||
this.PerformLayout(); | |||
} | |||
#endregion | |||
private System.Windows.Forms.Button btnGen; | |||
private System.Windows.Forms.TextBox txtIdList; | |||
private System.Windows.Forms.Button button1; | |||
} | |||
} | |||
@@ -0,0 +1,74 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel; | |||
using System.Data; | |||
using System.Drawing; | |||
using System.Linq; | |||
using System.Runtime.InteropServices; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using System.Windows.Forms; | |||
namespace WInFormApp | |||
{ | |||
public partial class StartForm : Form | |||
{ | |||
public StartForm() | |||
{ | |||
InitializeComponent(); | |||
} | |||
[DllImport("yitidgengo.dll", CallingConvention = CallingConvention.StdCall)] | |||
public static extern long NextId(); | |||
[DllImport("yitidgengo.dll", CallingConvention = CallingConvention.StdCall)] | |||
public static extern long NextId2(); | |||
[DllImport("yitidgengo.dll", CallingConvention = CallingConvention.StdCall)] | |||
public static extern long RegisterWorkerId(string ip, int port, string password, int maxWorkerIdNumber); | |||
//public static extern ulong RegisterWorkerId2(); | |||
[DllImport("yitidgengo.dll", CallingConvention = CallingConvention.StdCall)] | |||
public static extern long UnRegisterWorkerId(); | |||
[DllImport("yitidgen.dll", CallingConvention = CallingConvention.StdCall)] | |||
public static extern void SetWorkerId(uint workerId); | |||
[DllImport("yitidgen.dll", CallingConvention = CallingConvention.StdCall)] | |||
public static extern int Test(); | |||
[DllImport("yitidgen.dll", CallingConvention = CallingConvention.StdCall)] | |||
public static extern int GetWorkerId(string ip, int port); | |||
private void Form1_Load(object sender, EventArgs e) | |||
{ | |||
} | |||
private void btnGen_Click(object sender, EventArgs e) | |||
{ | |||
try | |||
{ | |||
var ip = "localhost"; | |||
//txtIdList.Text += RegisterWorkerId(Encoding.UTF8.GetBytes(ip), 6379) + "\r\n"; | |||
txtIdList.Text += RegisterWorkerId(ip, 6379, "", 4) + "\r\n"; | |||
//txtIdList.Text += RegisterWorkerId() + "\r\n"; | |||
//txtIdList.Text += Test() + "\r\n"; | |||
} | |||
catch (Exception ex) | |||
{ | |||
txtIdList.Text = ex.Message; | |||
} | |||
} | |||
private void button1_Click(object sender, EventArgs e) | |||
{ | |||
UnRegisterWorkerId(); | |||
// GetWorkerId("localhost", 6379); | |||
} | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
<root> | |||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> | |||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> | |||
<xsd:element name="root" msdata:IsDataSet="true"> | |||
<xsd:complexType> | |||
<xsd:choice maxOccurs="unbounded"> | |||
<xsd:element name="metadata"> | |||
<xsd:complexType> | |||
<xsd:sequence> | |||
<xsd:element name="value" type="xsd:string" minOccurs="0" /> | |||
</xsd:sequence> | |||
<xsd:attribute name="name" use="required" type="xsd:string" /> | |||
<xsd:attribute name="type" type="xsd:string" /> | |||
<xsd:attribute name="mimetype" type="xsd:string" /> | |||
<xsd:attribute ref="xml:space" /> | |||
</xsd:complexType> | |||
</xsd:element> | |||
<xsd:element name="assembly"> | |||
<xsd:complexType> | |||
<xsd:attribute name="alias" type="xsd:string" /> | |||
<xsd:attribute name="name" type="xsd:string" /> | |||
</xsd:complexType> | |||
</xsd:element> | |||
<xsd:element name="data"> | |||
<xsd:complexType> | |||
<xsd:sequence> | |||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> | |||
</xsd:sequence> | |||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> | |||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> | |||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> | |||
<xsd:attribute ref="xml:space" /> | |||
</xsd:complexType> | |||
</xsd:element> | |||
<xsd:element name="resheader"> | |||
<xsd:complexType> | |||
<xsd:sequence> | |||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | |||
</xsd:sequence> | |||
<xsd:attribute name="name" type="xsd:string" use="required" /> | |||
</xsd:complexType> | |||
</xsd:element> | |||
</xsd:choice> | |||
</xsd:complexType> | |||
</xsd:element> | |||
</xsd:schema> | |||
<resheader name="resmimetype"> | |||
<value>text/microsoft-resx</value> | |||
</resheader> | |||
<resheader name="version"> | |||
<value>2.0</value> | |||
</resheader> | |||
<resheader name="reader"> | |||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
</resheader> | |||
<resheader name="writer"> | |||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
</resheader> | |||
</root> |
@@ -0,0 +1,19 @@ | |||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"> | |||
<PropertyGroup> | |||
<OutputType>WinExe</OutputType> | |||
<TargetFramework>net5.0-windows</TargetFramework> | |||
<UseWindowsForms>true</UseWindowsForms> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<None Remove="yitidgen.dll" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Content Include="yitidgen.dll"> | |||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | |||
</Content> | |||
</ItemGroup> | |||
</Project> |
@@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yitter.IdGenerator", "Yitte | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yitter.IdGenTest", "Yitter.IdGenTest\Yitter.IdGenTest.csproj", "{67426F7D-0A3B-4645-B4D7-5487215D3E2B}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YitIdGen.WinFormApp", "YitIdGen.WinFormApp\YitIdGen.WinFormApp.csproj", "{1035D82E-3F37-4940-AA32-5D1E0E53AFA5}" | |||
EndProject | |||
Global | |||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
Debug|Any CPU = Debug|Any CPU | |||
@@ -21,6 +23,10 @@ Global | |||
{67426F7D-0A3B-4645-B4D7-5487215D3E2B}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{67426F7D-0A3B-4645-B4D7-5487215D3E2B}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{67426F7D-0A3B-4645-B4D7-5487215D3E2B}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{1035D82E-3F37-4940-AA32-5D1E0E53AFA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{1035D82E-3F37-4940-AA32-5D1E0E53AFA5}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{1035D82E-3F37-4940-AA32-5D1E0E53AFA5}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{1035D82E-3F37-4940-AA32-5D1E0E53AFA5}.Release|Any CPU.Build.0 = Release|Any CPU | |||
EndGlobalSection | |||
GlobalSection(SolutionProperties) = preSolution | |||
HideSolutionNode = FALSE | |||
@@ -15,7 +15,6 @@ namespace Yitter.OrgSystem.TestA | |||
public IList<long> idList = new List<long>(); | |||
private int GenIdCount; | |||
private int WorkerId; | |||
public GenTest(IIdGenerator idGen, int genIdCount, int workerId) | |||
{ | |||
@@ -55,9 +55,9 @@ namespace Yitter.OrgSystem.TestA | |||
while (true) | |||
{ | |||
//RunSingle(); | |||
RunSingle(); | |||
//CallDll(); | |||
//Go(options); | |||
CallDll(); | |||
Thread.Sleep(1000); // 每隔1秒执行一次Go | |||
} | |||
} | |||
@@ -65,13 +65,13 @@ namespace Yitter.OrgSystem.TestA | |||
//[DllImport("yitidgenc.dll", CallingConvention = CallingConvention.StdCall)] | |||
//public static extern long NextId(); | |||
[DllImport("yitidgenc.dll", CallingConvention = CallingConvention.StdCall)] | |||
[DllImport("yitidgengo.dll", CallingConvention = CallingConvention.StdCall)] | |||
public static extern long NextId(); | |||
[DllImport("yitidgenc.dll", CallingConvention = CallingConvention.StdCall)] | |||
[DllImport("yitidgen.dll", CallingConvention = CallingConvention.StdCall)] | |||
public static extern void SetWorkerId(uint workerId); | |||
[DllImport("yitidgenc.dll", CallingConvention = CallingConvention.StdCall)] | |||
[DllImport("yitidgen.dll", CallingConvention = CallingConvention.StdCall)] | |||
public static extern int TestId(); | |||
private static void CallDll() | |||
@@ -1,47 +0,0 @@ | |||
/* | |||
* 版权属于:yitter(yitter@126.com) | |||
* 代码编辑:guoyahao | |||
* 代码修订:yitter | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package gen | |||
import ( | |||
"sync" | |||
"yitidgen/contract" | |||
) | |||
var ins *YitIdHelper | |||
var once sync.Once | |||
type YitIdHelper struct { | |||
idGenInstance interface { | |||
NewLong() uint64 | |||
} | |||
} | |||
func GetIns() *YitIdHelper { | |||
once.Do(func() { | |||
ins = &YitIdHelper{} | |||
}) | |||
return ins | |||
} | |||
func (yih *YitIdHelper) GetIdGenInstance() interface{} { | |||
return yih.idGenInstance | |||
} | |||
func (yih *YitIdHelper) SetIdGenerator(options *contract.IdGeneratorOptions) { | |||
yih.idGenInstance = NewDefaultIdGenerator(options) | |||
} | |||
func (yih *YitIdHelper) NextId() uint64 { | |||
once.Do(func() { | |||
if yih.idGenInstance == nil { | |||
options := contract.NewIdGeneratorOptions(1) | |||
yih.idGenInstance = NewDefaultIdGenerator(options) | |||
} | |||
}) | |||
return yih.idGenInstance.NewLong() | |||
} |
@@ -1 +1,9 @@ | |||
module "yitidgen" | |||
module yitidgen | |||
go 1.16 | |||
require ( | |||
github.com/go-redis/redis v6.15.9+incompatible | |||
github.com/onsi/ginkgo v1.15.2 // indirect | |||
github.com/onsi/gomega v1.11.0 // indirect | |||
) |
@@ -0,0 +1,82 @@ | |||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= | |||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= | |||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= | |||
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= | |||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= | |||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | |||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= | |||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= | |||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= | |||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= | |||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= | |||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | |||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= | |||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | |||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | |||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | |||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= | |||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= | |||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | |||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= | |||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= | |||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | |||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | |||
github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= | |||
github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= | |||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= | |||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= | |||
github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug= | |||
github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= | |||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | |||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | |||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= | |||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | |||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U= | |||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | |||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw= | |||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= | |||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | |||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | |||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= | |||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= | |||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= | |||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | |||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= | |||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= | |||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= | |||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | |||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | |||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | |||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= | |||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= | |||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= | |||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= |
@@ -4,7 +4,7 @@ | |||
* 代码修订:yitter | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package gen | |||
package idgen | |||
import ( | |||
"time" |
@@ -0,0 +1,68 @@ | |||
/* | |||
* 版权属于:yitter(yitter@126.com) | |||
* 代码编辑:guoyahao | |||
* 代码修订:yitter | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package idgen | |||
import ( | |||
"sync" | |||
"yitidgen/contract" | |||
) | |||
//var yitIdHelper *YitIdHelper | |||
//var once sync.Once | |||
var idGenerator *DefaultIdGenerator | |||
var singletonMutex sync.Mutex | |||
type YitIdHelper struct { | |||
idGenInstance interface { | |||
NewLong() uint64 | |||
} | |||
} | |||
// | |||
//func GetIns() *YitIdHelper { | |||
// once.Do(func() { | |||
// yitIdHelper = &YitIdHelper{} | |||
// }) | |||
// return yitIdHelper | |||
//} | |||
// | |||
//func (yih *YitIdHelper) GetIdGenInstance() interface{} { | |||
// return yih.idGenInstance | |||
//} | |||
// | |||
//func (yih *YitIdHelper) SetIdGenerator(options *contract.IdGeneratorOptions) { | |||
// yih.idGenInstance = NewDefaultIdGenerator(options) | |||
//} | |||
// | |||
//func (yih *YitIdHelper) NextId() uint64 { | |||
// once.Do(func() { | |||
// if yih.idGenInstance == nil { | |||
// options := contract.NewIdGeneratorOptions(1) | |||
// yih.idGenInstance = NewDefaultIdGenerator(options) | |||
// } | |||
// }) | |||
// | |||
// return yih.idGenInstance.NewLong() | |||
//} | |||
func SetIdGenerator(options *contract.IdGeneratorOptions) { | |||
singletonMutex.Lock() | |||
idGenerator = NewDefaultIdGenerator(options) | |||
singletonMutex.Unlock() | |||
} | |||
func NextId() uint64 { | |||
if idGenerator == nil { | |||
singletonMutex.Lock() | |||
options := contract.NewIdGeneratorOptions(1) | |||
idGenerator = NewDefaultIdGenerator(options) | |||
singletonMutex.Unlock() | |||
} | |||
return idGenerator.NewLong() | |||
} |
@@ -0,0 +1,67 @@ | |||
package main | |||
import ( | |||
"C" | |||
"fmt" | |||
"time" | |||
"yitidgen/contract" | |||
"yitidgen/idgen" | |||
"yitidgen/regworkerid" | |||
) | |||
//export SetOptions | |||
func SetOptions(workerId uint16) { | |||
var options = contract.NewIdGeneratorOptions(workerId) | |||
idgen.SetIdGenerator(options) | |||
} | |||
//export NextId | |||
func NextId() uint64 { | |||
return idgen.NextId() | |||
} | |||
//export RegisterWorkerId | |||
func RegisterWorkerId(ip *C.char, port int, password *C.char, maxWorkerId int) int { | |||
return regworkerid.RegisterWorkerId(C.GoString(ip), port, C.GoString(password), maxWorkerId) | |||
} | |||
//export UnRegisterWorkerId | |||
func UnRegisterWorkerId() { | |||
regworkerid.UnRegisterWorkerId() | |||
} | |||
func main() { | |||
// 方法一:直接采用默认方法生成一个Id | |||
fmt.Println("生成的Id:", idgen.NextId()) | |||
fmt.Println("生成的Id:", regworkerid.RegisterWorkerId("localhost", 6379, "", 4)) | |||
return | |||
// 方法二:自定义参数 | |||
var options = contract.NewIdGeneratorOptions(1) | |||
options.WorkerIdBitLength = 6 | |||
options.SeqBitLength = 6 | |||
options.TopOverCostCount = 2000 | |||
options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6 | |||
idgen.SetIdGenerator(options) | |||
var genCount = 50000 | |||
for { | |||
var begin = time.Now().UnixNano() / 1e6 | |||
for i := 0; i < genCount; i++ { | |||
idgen.NextId() | |||
} | |||
var end = time.Now().UnixNano() / 1e6 | |||
fmt.Println(end - begin) | |||
time.Sleep(time.Duration(1000) * time.Millisecond) | |||
} | |||
} | |||
// go build -o target\yitidgengo.dll -buildmode=c-shared main.go | |||
//var yid = idgen.YitIdHelper{} | |||
//yid.SetIdGenerator(options) | |||
//fmt.Println(yid.NextId()) |
@@ -0,0 +1,230 @@ | |||
package regworkerid | |||
import ( | |||
"fmt" | |||
"github.com/go-redis/redis" | |||
"strconv" | |||
"sync" | |||
"time" | |||
) | |||
var Client *redis.Client | |||
var _usingWorkerId int = -1 | |||
var _maxWorkerId int = 0 | |||
var _loopCount int = 0 | |||
var _liftIndex int = -1 | |||
var _workerIdLock sync.Mutex | |||
const CurrentWidIndexKey string = "IdGen:WorkerId:Index" | |||
const WidKeyPrefix string = "IdGen:WorkerId:Value:" | |||
const WorkerIdFlag = "Y" // WorkerId 存储标记 | |||
const WorkerIdLifeTimeSeconds = 15 // WorkerIdFlag 有效期(单位秒,最好是3的倍数) | |||
const Log = false | |||
func UnRegisterWorkerId() { | |||
if _usingWorkerId < 0 { | |||
return | |||
} | |||
_workerIdLock.Lock() | |||
Client.Del(WidKeyPrefix + strconv.Itoa(_usingWorkerId)) | |||
_usingWorkerId = -1 | |||
_liftIndex = -1 | |||
_workerIdLock.Unlock() | |||
} | |||
func RegisterWorkerId(ip string, port int, password string, maxWorkerId int) int { | |||
// maxWorkerId不能小于0 | |||
if maxWorkerId < 0 { | |||
return -1 | |||
} | |||
// 如果当前已注册过 WorkerId,则先注销,并终止先前的自动续期线程 | |||
if _usingWorkerId > -1 { | |||
UnRegisterWorkerId() | |||
} | |||
_maxWorkerId = maxWorkerId | |||
Client = redis.NewClient(&redis.Options{ | |||
Addr: string(ip) + ":" + strconv.Itoa(port), | |||
PoolSize: 1000, | |||
ReadTimeout: time.Millisecond * time.Duration(100), | |||
WriteTimeout: time.Millisecond * time.Duration(100), | |||
IdleTimeout: time.Second * time.Duration(60), | |||
Password: password, | |||
}) | |||
_, err := Client.Ping().Result() | |||
if err != nil { | |||
panic("init redis error") | |||
} else { | |||
if Log { | |||
fmt.Println("init redis ok") | |||
} | |||
} | |||
_loopCount = 0 | |||
return getNextWorkerId() | |||
} | |||
func getNextWorkerId() int { | |||
// 获取当前 WorkerIdIndex | |||
// var currentId = int(Client.Incr(CurrentWidIndexKey).Val()) | |||
r, err := Client.Incr(CurrentWidIndexKey).Result() | |||
if err != nil { | |||
return 0 | |||
} | |||
currentId := int(r) | |||
if Log { | |||
fmt.Println("Begin currentId:" + strconv.Itoa(currentId)) | |||
} | |||
// 如果 Index 大于最大值,则重置 | |||
if currentId > _maxWorkerId { | |||
if canReset() { | |||
// 当前应用获得重置 WorkerIdIndex 的权限 | |||
setWorkerIdIndex(-1) | |||
endReset() // 此步有可能不被执行? | |||
_loopCount++ | |||
// 超过一定次数,直接终止操作 | |||
if _loopCount > 10 { | |||
return -1 | |||
} | |||
// if _loopCount > 2 { | |||
// 如果超过2个循环,则暂停1s | |||
time.Sleep(time.Duration(500*_loopCount) * time.Millisecond) | |||
//_loopCount = 0 | |||
//} | |||
if Log { | |||
fmt.Println("canReset loop") | |||
} | |||
return getNextWorkerId() | |||
} else { | |||
// 如果有其它应用正在编辑,则本应用暂停1s后,再继续 | |||
time.Sleep(time.Duration(1000) * time.Millisecond) | |||
if Log { | |||
fmt.Println("not canReset loop") | |||
} | |||
return getNextWorkerId() | |||
} | |||
} | |||
if Log { | |||
fmt.Println("currentId:" + strconv.Itoa(currentId)) | |||
} | |||
if isAvailable(currentId) { | |||
if Log { | |||
fmt.Println("AA: isAvailable:" + strconv.Itoa(currentId)) | |||
} | |||
// 最新获得的 WorkerIdIndex,在 redis 中是可用状态 | |||
setWorkerIdFlag(currentId) | |||
_usingWorkerId = currentId | |||
// 获取到可用 WorkerId 后,启用新线程,每隔 1/3个 WorkerIdLifeTimeSeconds 时间,向服务器续期(延长一次 LifeTime) | |||
_liftIndex++ | |||
go extendWorkerIdLifeTime(_liftIndex) | |||
return currentId | |||
} else { | |||
if Log { | |||
fmt.Println("BB: not isAvailable:" + strconv.Itoa(currentId)) | |||
} | |||
// 最新获得的 WorkerIdIndex,在 redis 中是不可用状态,则继续下一个 WorkerIdIndex | |||
return getNextWorkerId() | |||
} | |||
} | |||
func extendWorkerIdLifeTime(lifeIndex int) { | |||
var index = lifeIndex | |||
for { | |||
time.Sleep(time.Duration(WorkerIdLifeTimeSeconds/3) * time.Millisecond) | |||
_workerIdLock.Lock() | |||
if index != _liftIndex { | |||
// 如果临时变量 index 不等于 全局变量 _liftIndex,表明全局状态被修改,当前线程可终止 | |||
break | |||
} | |||
// 已经被注销,则终止(此步是上一步的二次验证) | |||
if _usingWorkerId < 0 { | |||
break | |||
} | |||
extendWorkerIdFlag(_usingWorkerId) | |||
_workerIdLock.Unlock() | |||
} | |||
} | |||
func get(key string) (string, bool) { | |||
r, err := Client.Get(key).Result() | |||
if err != nil { | |||
return "", false | |||
} | |||
return r, true | |||
} | |||
func set(key string, val string, expTime int32) { | |||
Client.Set(key, val, time.Duration(expTime)*time.Second) | |||
} | |||
func setWorkerIdIndex(val int) { | |||
Client.Set(CurrentWidIndexKey, val, 0) | |||
} | |||
func setWorkerIdFlag(index int) { | |||
Client.Set(WidKeyPrefix+strconv.Itoa(index), WorkerIdFlag, time.Duration(WorkerIdLifeTimeSeconds)*time.Second) | |||
} | |||
func extendWorkerIdFlag(index int) { | |||
Client.Expire(WidKeyPrefix+strconv.Itoa(index), time.Duration(WorkerIdLifeTimeSeconds)*time.Second) | |||
} | |||
func canReset() bool { | |||
r, err := Client.Incr(WidKeyPrefix + "Edit").Result() | |||
if err != nil { | |||
return false | |||
} | |||
if Log { | |||
fmt.Println("canReset:" + string(r)) | |||
} | |||
return r != 1 | |||
} | |||
func endReset() { | |||
// Client.Set(WidKeyPrefix+"Edit", 0, time.Duration(2)*time.Second) | |||
Client.Set(WidKeyPrefix+"Edit", 0, 0) | |||
} | |||
func getWorkerIdFlag(index int) (string, bool) { | |||
r, err := Client.Get(WidKeyPrefix + strconv.Itoa(index)).Result() | |||
if err != nil { | |||
return "", false | |||
} | |||
return r, true | |||
} | |||
func isAvailable(index int) bool { | |||
r, err := Client.Get(WidKeyPrefix + strconv.Itoa(index)).Result() | |||
if Log { | |||
fmt.Println("XX isAvailable:" + r) | |||
fmt.Println("YY isAvailable:" + err.Error()) | |||
} | |||
if err != nil { | |||
if err.Error() == "redis: nil" { | |||
return true | |||
} | |||
return false | |||
} | |||
return r != WorkerIdFlag | |||
} |
@@ -0,0 +1,75 @@ | |||
/* Code generated by cmd/cgo; DO NOT EDIT. */ | |||
/* package command-line-arguments */ | |||
#line 1 "cgo-builtin-export-prolog" | |||
#include <stddef.h> /* for ptrdiff_t below */ | |||
#ifndef GO_CGO_EXPORT_PROLOGUE_H | |||
#define GO_CGO_EXPORT_PROLOGUE_H | |||
#ifndef GO_CGO_GOSTRING_TYPEDEF | |||
typedef struct { const char *p; ptrdiff_t n; } _GoString_; | |||
#endif | |||
#endif | |||
/* Start of preamble from import "C" comments. */ | |||
/* End of preamble from import "C" comments. */ | |||
/* Start of boilerplate cgo prologue. */ | |||
#line 1 "cgo-gcc-export-header-prolog" | |||
#ifndef GO_CGO_PROLOGUE_H | |||
#define GO_CGO_PROLOGUE_H | |||
typedef signed char GoInt8; | |||
typedef unsigned char GoUint8; | |||
typedef short GoInt16; | |||
typedef unsigned short GoUint16; | |||
typedef int GoInt32; | |||
typedef unsigned int GoUint32; | |||
typedef long long GoInt64; | |||
typedef unsigned long long GoUint64; | |||
typedef GoInt64 GoInt; | |||
typedef GoUint64 GoUint; | |||
typedef __SIZE_TYPE__ GoUintptr; | |||
typedef float GoFloat32; | |||
typedef double GoFloat64; | |||
typedef float _Complex GoComplex64; | |||
typedef double _Complex GoComplex128; | |||
/* | |||
static assertion to make sure the file is being used on architecture | |||
at least with matching size of GoInt. | |||
*/ | |||
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; | |||
#ifndef GO_CGO_GOSTRING_TYPEDEF | |||
typedef _GoString_ GoString; | |||
#endif | |||
typedef void *GoMap; | |||
typedef void *GoChan; | |||
typedef struct { void *t; void *v; } GoInterface; | |||
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; | |||
#endif | |||
/* End of boilerplate cgo prologue. */ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
extern __declspec(dllexport) GoUint64 NextId(); | |||
#ifdef __cplusplus | |||
} | |||
#endif |
@@ -0,0 +1,75 @@ | |||
/* Code generated by cmd/cgo; DO NOT EDIT. */ | |||
/* package command-line-arguments */ | |||
#line 1 "cgo-builtin-export-prolog" | |||
#include <stddef.h> /* for ptrdiff_t below */ | |||
#ifndef GO_CGO_EXPORT_PROLOGUE_H | |||
#define GO_CGO_EXPORT_PROLOGUE_H | |||
#ifndef GO_CGO_GOSTRING_TYPEDEF | |||
typedef struct { const char *p; ptrdiff_t n; } _GoString_; | |||
#endif | |||
#endif | |||
/* Start of preamble from import "C" comments. */ | |||
/* End of preamble from import "C" comments. */ | |||
/* Start of boilerplate cgo prologue. */ | |||
#line 1 "cgo-gcc-export-header-prolog" | |||
#ifndef GO_CGO_PROLOGUE_H | |||
#define GO_CGO_PROLOGUE_H | |||
typedef signed char GoInt8; | |||
typedef unsigned char GoUint8; | |||
typedef short GoInt16; | |||
typedef unsigned short GoUint16; | |||
typedef int GoInt32; | |||
typedef unsigned int GoUint32; | |||
typedef long long GoInt64; | |||
typedef unsigned long long GoUint64; | |||
typedef GoInt64 GoInt; | |||
typedef GoUint64 GoUint; | |||
typedef __SIZE_TYPE__ GoUintptr; | |||
typedef float GoFloat32; | |||
typedef double GoFloat64; | |||
typedef float _Complex GoComplex64; | |||
typedef double _Complex GoComplex128; | |||
/* | |||
static assertion to make sure the file is being used on architecture | |||
at least with matching size of GoInt. | |||
*/ | |||
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; | |||
#ifndef GO_CGO_GOSTRING_TYPEDEF | |||
typedef _GoString_ GoString; | |||
#endif | |||
typedef void *GoMap; | |||
typedef void *GoChan; | |||
typedef struct { void *t; void *v; } GoInterface; | |||
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; | |||
#endif | |||
/* End of boilerplate cgo prologue. */ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
extern __declspec(dllexport) GoUint64 NextId(); | |||
#ifdef __cplusplus | |||
} | |||
#endif |
@@ -0,0 +1,78 @@ | |||
/* Code generated by cmd/cgo; DO NOT EDIT. */ | |||
/* package command-line-arguments */ | |||
#line 1 "cgo-builtin-export-prolog" | |||
#include <stddef.h> /* for ptrdiff_t below */ | |||
#ifndef GO_CGO_EXPORT_PROLOGUE_H | |||
#define GO_CGO_EXPORT_PROLOGUE_H | |||
#ifndef GO_CGO_GOSTRING_TYPEDEF | |||
typedef struct { const char *p; ptrdiff_t n; } _GoString_; | |||
#endif | |||
#endif | |||
/* Start of preamble from import "C" comments. */ | |||
/* End of preamble from import "C" comments. */ | |||
/* Start of boilerplate cgo prologue. */ | |||
#line 1 "cgo-gcc-export-header-prolog" | |||
#ifndef GO_CGO_PROLOGUE_H | |||
#define GO_CGO_PROLOGUE_H | |||
typedef signed char GoInt8; | |||
typedef unsigned char GoUint8; | |||
typedef short GoInt16; | |||
typedef unsigned short GoUint16; | |||
typedef int GoInt32; | |||
typedef unsigned int GoUint32; | |||
typedef long long GoInt64; | |||
typedef unsigned long long GoUint64; | |||
typedef GoInt64 GoInt; | |||
typedef GoUint64 GoUint; | |||
typedef __SIZE_TYPE__ GoUintptr; | |||
typedef float GoFloat32; | |||
typedef double GoFloat64; | |||
typedef float _Complex GoComplex64; | |||
typedef double _Complex GoComplex128; | |||
/* | |||
static assertion to make sure the file is being used on architecture | |||
at least with matching size of GoInt. | |||
*/ | |||
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; | |||
#ifndef GO_CGO_GOSTRING_TYPEDEF | |||
typedef _GoString_ GoString; | |||
#endif | |||
typedef void *GoMap; | |||
typedef void *GoChan; | |||
typedef struct { void *t; void *v; } GoInterface; | |||
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; | |||
#endif | |||
/* End of boilerplate cgo prologue. */ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
extern __declspec(dllexport) void SetOptions(GoUint16 workerId); | |||
extern __declspec(dllexport) GoUint64 NextId(); | |||
extern __declspec(dllexport) GoInt RegisterWorkerId(char* ip, GoInt port, char* password, GoInt maxWorkerId); | |||
extern __declspec(dllexport) void UnRegisterWorkerId(); | |||
#ifdef __cplusplus | |||
} | |||
#endif |
@@ -1,43 +0,0 @@ | |||
package main | |||
import ( | |||
"C" | |||
"fmt" | |||
"time" | |||
"yitidgen/contract" | |||
"yitidgen/gen" | |||
) | |||
//export NextId | |||
func NextId() uint64{ | |||
return gen.GetIns().NextId() | |||
} | |||
func main() { | |||
// 方法一:直接采用默认方法生成一个Id | |||
var yid = gen.YitIdHelper{} | |||
fmt.Println(yid.NextId()) | |||
// 方法二:自定义参数 | |||
var options = contract.NewIdGeneratorOptions(1) | |||
//options.WorkerIdBitLength = 6 | |||
//options.SeqBitLength = 6 | |||
//options.TopOverCostCount = 2000 | |||
//options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6 | |||
yid.SetIdGenerator(options) | |||
var times = 50000 | |||
for { | |||
var begin = time.Now().UnixNano() / 1e6 | |||
for i := 0; i < times; i++ { | |||
yid.NextId() | |||
} | |||
var end = time.Now().UnixNano() / 1e6 | |||
fmt.Println(end - begin) | |||
time.Sleep(time.Duration(1000) * time.Millisecond) | |||
} | |||
} |
@@ -1,4 +0,0 @@ | |||
# idgenerator | |||
something is going on. | |||
@@ -1,4 +1,4 @@ | |||
# IdGenerator SnowFlake 雪花算法 原生多语言版本 顶尖优化 超强效能 | |||
# 唯一ID生成器 IdGenerator SnowFlake 雪花算法 原生多语言源码 | |||
## 介绍 | |||
@@ -8,6 +8,8 @@ | |||
3.原生支持 C#/Java/Go/Rust/C 等语言,并由 Rust 提供 PHP、Python、Node.js、Ruby 等语言多线程安全调用库(FFI)。 | |||
4.支持单服务部署、多服务部署、容器自动化服务 | |||
## 技术支持 | |||
@@ -27,13 +29,13 @@ QQ群:646049993 | |||
4.如果这样的主键值太长,超过前端 JS Number 类型最大值,须把 Long 型转换为 String 型,你会觉得有点沮丧。 | |||
5.哪怕 Guid 能自增,但占用空间大,索引速度慢,所以你也不想用它。 | |||
5.尽管 Guid 能自增,但占用空间大,索引速度慢,你也不想用它。 | |||
6.你的应用实例可能超过50个,每个并发请求可达10W/s。 | |||
6.应用实例可能超过50个,每个并发请求可达10W/s。 | |||
7.在容器环境部署应用(水平扩展、自动伸缩)。 | |||
8.你可不想 Id 生成器依赖 redis 的自增操作。 | |||
8.不想依赖 redis 的自增操作。 | |||
9.你希望系统运行 100 年以上。 | |||
@@ -164,7 +166,15 @@ ID示例(基于默认配置): | |||
7.不要修改核心算法。本算法内部参数较多,逻辑较为复杂,在你尚未掌握核心逻辑时,请勿尝试修改核心代码且用于生产环境,除非通过大量细致、科学的测试验证。 | |||
#### 大型分布式集成 | |||
#### 自动/手动 设置 WorkerId | |||
1.如果Id生成服务是明确的,可在初始化时,手动设置 WorkerId。 | |||
2.如果Id生成服务是不明确的,如容器环境:动态的、自动执行、生命周期完全自动化,可在初始化时通过Redis,自动申请 WorkerId,详见“Tools/AutoRegisterWorkerId” | |||
#### 其它分布式集成 | |||
1.可增加 WorkerIdBitLength 到最大20,支持 1,048,576 个节点,且不影响上述并发性能。[算法支持] | |||
@@ -1,11 +1,28 @@ | |||
# This file is automatically @generated by Cargo. | |||
# It is not intended for manual editing. | |||
[[package]] | |||
name = "async-trait" | |||
version = "0.1.48" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "36ea56748e10732c49404c153638a15ec3d6211ec5ff35d9bb20e13b93576adf" | |||
dependencies = [ | |||
"proc-macro2", | |||
"quote", | |||
"syn", | |||
] | |||
[[package]] | |||
name = "autocfg" | |||
version = "1.0.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" | |||
[[package]] | |||
name = "bytes" | |||
version = "1.0.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" | |||
[[package]] | |||
name = "chrono" | |||
version = "0.4.19" | |||
@@ -19,6 +36,49 @@ dependencies = [ | |||
"winapi", | |||
] | |||
[[package]] | |||
name = "combine" | |||
version = "4.5.2" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "cc4369b5e4c0cddf64ad8981c0111e7df4f7078f4d6ba98fb31f2e17c4c57b7e" | |||
dependencies = [ | |||
"bytes", | |||
"memchr", | |||
] | |||
[[package]] | |||
name = "dtoa" | |||
version = "0.4.8" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" | |||
[[package]] | |||
name = "form_urlencoded" | |||
version = "1.0.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" | |||
dependencies = [ | |||
"matches", | |||
"percent-encoding", | |||
] | |||
[[package]] | |||
name = "idna" | |||
version = "0.2.2" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21" | |||
dependencies = [ | |||
"matches", | |||
"unicode-bidi", | |||
"unicode-normalization", | |||
] | |||
[[package]] | |||
name = "itoa" | |||
version = "0.4.7" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" | |||
[[package]] | |||
name = "lazy_static" | |||
version = "1.4.0" | |||
@@ -31,6 +91,18 @@ version = "0.2.90" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae" | |||
[[package]] | |||
name = "matches" | |||
version = "0.1.8" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" | |||
[[package]] | |||
name = "memchr" | |||
version = "2.3.4" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" | |||
[[package]] | |||
name = "num-integer" | |||
version = "0.1.44" | |||
@@ -50,6 +122,62 @@ dependencies = [ | |||
"autocfg", | |||
] | |||
[[package]] | |||
name = "percent-encoding" | |||
version = "2.1.0" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" | |||
[[package]] | |||
name = "proc-macro2" | |||
version = "1.0.24" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" | |||
dependencies = [ | |||
"unicode-xid", | |||
] | |||
[[package]] | |||
name = "quote" | |||
version = "1.0.9" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" | |||
dependencies = [ | |||
"proc-macro2", | |||
] | |||
[[package]] | |||
name = "redis" | |||
version = "0.20.0" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "eeb8f8d059ead7805e171fc22de8348a3d611c0f985aaa4f5cf6c0dfc7645407" | |||
dependencies = [ | |||
"async-trait", | |||
"combine", | |||
"dtoa", | |||
"itoa", | |||
"percent-encoding", | |||
"sha1", | |||
"url", | |||
] | |||
[[package]] | |||
name = "sha1" | |||
version = "0.6.0" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" | |||
[[package]] | |||
name = "syn" | |||
version = "1.0.67" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702" | |||
dependencies = [ | |||
"proc-macro2", | |||
"quote", | |||
"unicode-xid", | |||
] | |||
[[package]] | |||
name = "time" | |||
version = "0.1.44" | |||
@@ -61,6 +189,57 @@ dependencies = [ | |||
"winapi", | |||
] | |||
[[package]] | |||
name = "tinyvec" | |||
version = "1.1.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" | |||
dependencies = [ | |||
"tinyvec_macros", | |||
] | |||
[[package]] | |||
name = "tinyvec_macros" | |||
version = "0.1.0" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" | |||
[[package]] | |||
name = "unicode-bidi" | |||
version = "0.3.4" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" | |||
dependencies = [ | |||
"matches", | |||
] | |||
[[package]] | |||
name = "unicode-normalization" | |||
version = "0.1.17" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" | |||
dependencies = [ | |||
"tinyvec", | |||
] | |||
[[package]] | |||
name = "unicode-xid" | |||
version = "0.2.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" | |||
[[package]] | |||
name = "url" | |||
version = "2.2.1" | |||
source = "registry+https://github.com/rust-lang/crates.io-index" | |||
checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" | |||
dependencies = [ | |||
"form_urlencoded", | |||
"idna", | |||
"matches", | |||
"percent-encoding", | |||
] | |||
[[package]] | |||
name = "wasi" | |||
version = "0.10.0+wasi-snapshot-preview1" | |||
@@ -95,4 +274,6 @@ version = "1.0.0" | |||
dependencies = [ | |||
"chrono", | |||
"lazy_static", | |||
"libc", | |||
"redis", | |||
] |
@@ -9,6 +9,15 @@ edition = "2018" | |||
[dependencies] | |||
chrono = "0.4.10" | |||
lazy_static = "1.4.0" | |||
#simple_redis = "*" | |||
redis = "0.20.0" | |||
libc="*" | |||
#actix = "0.9.0" | |||
#actix-web = "2.0" | |||
#actix-rt = "1.0" | |||
#actix-redis = "0.8.0" | |||
#redis-async = "0.6.1" | |||
[lib] | |||
name = "yitidgen" | |||
@@ -3,6 +3,23 @@ mod yitgen; | |||
use yitgen::gen::YitIdHelper; | |||
use yitgen::contract::*; | |||
#[macro_use] | |||
extern crate lazy_static; | |||
extern crate redis; | |||
extern crate libc; | |||
use redis::Commands; | |||
use libc::{c_char, uint32_t}; | |||
use std::ffi::{CStr, CString}; | |||
use std::str; | |||
lazy_static! { | |||
//static ref TestValue: Vec<i32> = vec!(0); | |||
// static ref MAP: HashMap<u32, String> = HashMap::new(); | |||
} | |||
// #[export_name = "SetIdGenerator"] | |||
#[no_mangle] | |||
pub extern "C" fn SetIdGenerator(options: IdGeneratorOptions) { | |||
@@ -19,3 +36,64 @@ pub extern "C" fn NextId() -> i64 { | |||
YitIdHelper::NextId() | |||
} | |||
static mut TestValue: i32 = 0; | |||
#[no_mangle] | |||
pub extern "C" fn Test() -> i32 { | |||
unsafe { | |||
TestValue += 1; | |||
return TestValue; | |||
} | |||
} | |||
#[no_mangle] | |||
pub extern "C" fn GetWorkerId(ip: *const c_char, port: i32) -> redis::RedisResult<isize> { | |||
// let c_str = unsafe { | |||
// assert!(!ip.is_null()); | |||
// CStr::from_ptr(ip) | |||
// }; | |||
// | |||
// let r_str = c_str.to_str(); | |||
// connect to redis | |||
// let client = redis::Client::open(format!("redis://{}:{}/", String::from(r_str).to_string(), port))?; | |||
let client = redis::Client::open(format!("redis://localhost:{}/", port))?; | |||
let mut con = client.get_connection()?; | |||
// throw away the result, just make sure it does not fail | |||
unsafe { | |||
let _: () = con.set("my_key111", TestValue.clone())?; | |||
} | |||
con.get("my_key") | |||
// read back the key and return it. Because the return value | |||
// from the function is a result for integer this will automatically | |||
// convert into one. | |||
// | |||
// match simple_redis::create(&format!("redis://{}:{}/", ip, port)) { | |||
// Ok(mut client) => { | |||
// println!("Created Redis Client"); | |||
// | |||
// let valueString = TestValue.to_string(); | |||
// let valueString2 = (*TestValue).to_string(); | |||
// | |||
// match client.set("my_key", valueString) { | |||
// Err(error) => println!("Unable to set value in Redis: {}", error), | |||
// _ => println!("Value set in Redis") | |||
// }; | |||
// | |||
// match client.set("my_key2", valueString2) { | |||
// Err(error) => println!("Unable to set value in Redis: {}", error), | |||
// _ => println!("Value set in Redis") | |||
// }; | |||
// | |||
// match client.quit() { | |||
// Err(error) => println!("Error: {}", error), | |||
// _ => println!("Connection Closed.") | |||
// } | |||
// } | |||
// Err(error) => println!("Unable to create Redis client: {}", error) | |||
// } | |||
//return 1; | |||
} |
@@ -6,6 +6,7 @@ use std::thread; | |||
use chrono::Utc; | |||
use std::time::Duration; | |||
fn main() { | |||
println!("Hello, world! Rust"); | |||
@@ -22,6 +23,8 @@ fn main() { | |||
//... 可以继续设置其它 options 参数 | |||
YitIdHelper::SetIdGenerator(options); | |||
set_redis(); | |||
// 以下开始测试生成数据,默认5W,单线程,可以修改 multiThread=true 启用多线程。 | |||
loop { | |||
let mut i = 0; | |||
@@ -51,3 +54,24 @@ fn main() { | |||
} | |||
} | |||
fn set_redis() { | |||
// match simple_redis::create("redis://127.0.0.1:6379/") { | |||
// Ok(mut client) => { | |||
// println!("Created Redis Client"); | |||
// | |||
// match client.set("my_key", "my_value") { | |||
// Err(error) => println!("Unable to set value in Redis: {}", error), | |||
// _ => println!("Value set in Redis") | |||
// }; | |||
// | |||
// match client.quit() { | |||
// Err(error) => println!("Error: {}", error), | |||
// _ => println!("Connection Closed.") | |||
// } | |||
// }, | |||
// Err(error) => println!("Unable to create Redis client: {}", error) | |||
// } | |||
} | |||
@@ -6,7 +6,7 @@ use super::super::contract::*; | |||
use std::{thread}; | |||
use chrono::Utc; | |||
use std::thread::sleep; | |||
use lazy_static::lazy_static; | |||
// use lazy_static::lazy_static; | |||
pub struct SnowWorkerM1 { | |||
///基础时间 | |||
@@ -12,7 +12,7 @@ use std::sync::Mutex; | |||
use std::sync::Arc; | |||
use std::borrow::BorrowMut; | |||
static mut instance2: Option<Arc<Mutex<SnowWorkerM1>>> = None; | |||
// static mut instance2: Option<Arc<Mutex<SnowWorkerM1>>> = None; | |||
pub struct DefaultIdGenerator { | |||
pub Worker: SnowWorkerM1, | |||
@@ -0,0 +1,16 @@ | |||
# idgenerator | |||
## 关于AutoRegisterWorkerId | |||
这是自动注册 WorkerId 的工具。可在容器环境下集成使用。 | |||
## 步骤集成 | |||
全局执行一次: | |||
1.设置Redis连接。 | |||
2.获取 WorkerId,赋值给 IdGenerator。 | |||
@@ -0,0 +1,7 @@ | |||
# idgenerator | |||
## FFI 调用 | |||
Pyton、node.js、PHP 等可以通过 FFI 方式调用动态库生成 ID。 | |||
这里将提供不同操作系统的动态库 |